// Decompiled by DJ v3.11.11.95 Copyright 2009 Atanas Neshkov  Date: 2009-11-13 9:39:33
// Home Page: http://members.fortunecity.com/neshkov/dj.html  http://www.neshkov.com/dj.html - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Configuration.java

package org.hibernate.cfg;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element; 
import org.hibernate.EmptyInterceptor;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.InvalidMappingException;
import org.hibernate.MappingException;
import org.hibernate.MappingNotFoundException;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.FilterDefinition;
import org.hibernate.engine.Mapping;
import org.hibernate.event.AutoFlushEventListener;
import org.hibernate.event.DeleteEventListener;
import org.hibernate.event.DirtyCheckEventListener;
import org.hibernate.event.EventListeners;
import org.hibernate.event.EvictEventListener;
import org.hibernate.event.FlushEntityEventListener;
import org.hibernate.event.FlushEventListener;
import org.hibernate.event.InitializeCollectionEventListener;
import org.hibernate.event.LoadEventListener;
import org.hibernate.event.LockEventListener;
import org.hibernate.event.MergeEventListener;
import org.hibernate.event.PersistEventListener;
import org.hibernate.event.PostCollectionRecreateEventListener;
import org.hibernate.event.PostCollectionRemoveEventListener;
import org.hibernate.event.PostCollectionUpdateEventListener;
import org.hibernate.event.PostDeleteEventListener;
import org.hibernate.event.PostInsertEventListener;
import org.hibernate.event.PostLoadEventListener;
import org.hibernate.event.PostUpdateEventListener;
import org.hibernate.event.PreCollectionRecreateEventListener;
import org.hibernate.event.PreCollectionRemoveEventListener;
import org.hibernate.event.PreCollectionUpdateEventListener;
import org.hibernate.event.PreDeleteEventListener;
import org.hibernate.event.PreInsertEventListener;
import org.hibernate.event.PreLoadEventListener;
import org.hibernate.event.PreUpdateEventListener;
import org.hibernate.event.RefreshEventListener;
import org.hibernate.event.ReplicateEventListener;
import org.hibernate.event.SaveOrUpdateEventListener;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.impl.SessionFactoryImpl;
import org.hibernate.mapping.AuxiliaryDatabaseObject;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.IdentifierCollection;
import org.hibernate.mapping.Index; 
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.proxy.EntityNotFoundDelegate;
import org.hibernate.secure.JACCConfiguration;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
import org.hibernate.tool.hbm2ddl.TableMetadata;
import org.hibernate.type.SerializationException;
import org.hibernate.type.Type;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.CollectionHelper;
import org.hibernate.util.ConfigHelper;
import org.hibernate.util.PropertiesHelper;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.SerializationHelper;
import org.hibernate.util.StringHelper;
import org.hibernate.util.XMLHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

@SuppressWarnings("unchecked")
public class Configuration implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6211690182891794214L;
	private static Logger log = LoggerFactory.getLogger(Configuration.class);
	protected Map classes;
	protected Map imports;
	protected Map collections;
	protected Map tables;
	protected List auxiliaryDatabaseObjects;
	protected Map sqlFunctions;
	protected Map namedQueries;
	protected Map namedSqlQueries;
	protected Map sqlResultSetMappings;
	protected Map filterDefinitions;
	protected List secondPasses;
	protected List propertyReferences;
	protected Map extendsQueue;
	protected Map tableNameBinding;
	protected Map columnNameBindingPerTable;
	private Interceptor interceptor;
	private Properties properties;
	private EntityResolver entityResolver;
	private EntityNotFoundDelegate entityNotFoundDelegate;
	protected transient XMLHelper xmlHelper;
	protected transient Map typeDefs;
	protected NamingStrategy namingStrategy;
	private EventListeners eventListeners;
	protected final SettingsFactory settingsFactory;
	private SessionFactoryObserver sessionFactoryObserver;
	private transient Mapping mapping = buildMapping();

	protected void reset() {
		classes = new HashMap();
		imports = new HashMap();
		collections = new HashMap();
		tables = new TreeMap();
		namedQueries = new HashMap();
		namedSqlQueries = new HashMap();
		sqlResultSetMappings = new HashMap();
		xmlHelper = new XMLHelper();
		typeDefs = new HashMap();
		propertyReferences = new ArrayList();
		secondPasses = new ArrayList();
		interceptor = EmptyInterceptor.INSTANCE;
		properties = Environment.getProperties();
		entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
		eventListeners = new EventListeners();
		filterDefinitions = new HashMap();
		extendsQueue = new HashMap();
		auxiliaryDatabaseObjects = new ArrayList();
		tableNameBinding = new HashMap();
		columnNameBindingPerTable = new HashMap();
		namingStrategy = DefaultNamingStrategy.INSTANCE;
		sqlFunctions = new HashMap();
	}
	
	public Mapping getMapping()
	{
		return this.mapping;
	}
	protected Configuration(SettingsFactory settingsFactory) {
		mapping = buildMapping();
		this.settingsFactory = settingsFactory;
		reset();
	}

	public Configuration() {
		this(new SettingsFactory());
	}

	public Iterator getClassMappings() {
		return classes.values().iterator();
	}

	public Iterator getCollectionMappings() {
		return collections.values().iterator();
	}

	public Iterator getTableMappings() {
		return tables.values().iterator();
	}

	public PersistentClass getClassMapping(String entityName) {
		return (PersistentClass) classes.get(entityName);
	}

	public Collection getCollectionMapping(String role) {
		return (Collection) collections.get(role);
	}

	public void setEntityResolver(EntityResolver entityResolver) {
		this.entityResolver = entityResolver;
	}

	public EntityResolver getEntityResolver() {
		return entityResolver;
	}

	public EntityNotFoundDelegate getEntityNotFoundDelegate() {
		return entityNotFoundDelegate;
	}

	public void setEntityNotFoundDelegate(
			EntityNotFoundDelegate entityNotFoundDelegate) {
		this.entityNotFoundDelegate = entityNotFoundDelegate;
	}

	public Configuration addFile(String xmlFile) throws MappingException {
		return addFile(new File(xmlFile));
	}

	public Configuration addFile(File xmlFile) throws MappingException {
		log.info("Reading mappings from file: " + xmlFile.getPath());
		if (!xmlFile.exists())
			throw new MappingNotFoundException("file", xmlFile.toString());
		try {
			List errors = new ArrayList();
			Document doc = xmlHelper.createSAXReader(xmlFile.toString(),
					errors, entityResolver).read(xmlFile);
			if (errors.size() != 0) {
				throw new InvalidMappingException("file", xmlFile.toString(),
						(Throwable) errors.get(0));
			} else {
				add(doc);
				return this;
			}
		} catch (InvalidMappingException e) {
			throw e;
		} catch (MappingNotFoundException e) {
			throw e;
		} catch (Exception e) {
			throw new InvalidMappingException("file", xmlFile.toString(), e);
		}
	}

	public Configuration addCacheableFile(File xmlFile) throws MappingException {
		try {
			File cachedFile = new File(xmlFile.getAbsolutePath() + ".bin");
			Document doc = null;
			boolean useCachedFile = xmlFile.exists() && cachedFile.exists()
					&& xmlFile.lastModified() < cachedFile.lastModified();
			if (useCachedFile)
				try {
					log.info("Reading mappings from cache file: " + cachedFile);
					doc = (Document) SerializationHelper
							.deserialize(new FileInputStream(cachedFile));
				} catch (SerializationException e) {
					log.warn("Could not deserialize cache file: "
							+ cachedFile.getPath(), e);
				} catch (FileNotFoundException e) {
					log.warn("I/O reported cached file could not be found : "
							+ cachedFile.getPath(), e);
				}
			if (doc == null) {
				if (!xmlFile.exists())
					throw new MappingNotFoundException("file", xmlFile
							.toString());
				log.info("Reading mappings from file: " + xmlFile);
				List errors = new ArrayList();
				try {
					doc = xmlHelper.createSAXReader(xmlFile.getAbsolutePath(),
							errors, entityResolver).read(xmlFile);
					if (errors.size() != 0)
						throw new MappingException("invalid mapping",
								(Throwable) errors.get(0));
				} catch (DocumentException e) {
					throw new MappingException("invalid mapping", e);
				}
				try {
					log.debug("Writing cache file for: " + xmlFile + " to: "
							+ cachedFile);
					SerializationHelper.serialize((Serializable) doc,
							new FileOutputStream(cachedFile));
				} catch (SerializationException e) {
					log.warn("Could not write cached file: " + cachedFile, e);
				} catch (FileNotFoundException e) {
					log.warn("I/O reported error writing cached file : "
							+ cachedFile.getPath(), e);
				}
			}
			add(doc);
			return this;
		} catch (InvalidMappingException e) {
			throw e;
		} catch (MappingNotFoundException e) {
			throw e;
		} catch (Exception e) {
			throw new InvalidMappingException("file", xmlFile.toString(), e);
		}
	}

	public Configuration addCacheableFile(String xmlFile)
			throws MappingException {
		return addCacheableFile(new File(xmlFile));
	}

	public Configuration addXML(String xml) throws MappingException {
		if (log.isDebugEnabled())
			log.debug("Mapping XML:\n" + xml);
		try {
			List errors = new ArrayList();
			Document doc = xmlHelper.createSAXReader("XML String", errors,
					entityResolver).read(new StringReader(xml));
			if (errors.size() != 0)
				throw new MappingException("invalid mapping",
						(Throwable) errors.get(0));
			add(doc);
		} catch (DocumentException e) {
			throw new MappingException(
					"Could not parse mapping document in XML string", e);
		}
		return this;
	}

	public Configuration addURL(URL url) throws MappingException {
		if (log.isDebugEnabled())
			log.debug("Reading mapping document from URL:"
					+ url.toExternalForm());
		try {
			addInputStream(url.openStream());
		} catch (InvalidMappingException e) {
			throw new InvalidMappingException("URL", url.toExternalForm(), e
					.getCause());
		} catch (Exception e) {
			throw new InvalidMappingException("URL", url.toExternalForm(), e);
		}
		return this;
	}

	public Configuration addDocument(org.w3c.dom.Document doc)
			throws MappingException {
		if (log.isDebugEnabled())
			log.debug("Mapping document:\n" + doc);
		add(xmlHelper.createDOMReader().read(doc));
		return this;
	}

	public Configuration addInputStream(InputStream xmlInputStream)
			throws MappingException {
		Configuration configuration;
		try {
			List errors = new ArrayList();
			Document doc = xmlHelper.createSAXReader("XML InputStream", errors,
					entityResolver).read(new InputSource(xmlInputStream));
			if (errors.size() != 0)
				throw new InvalidMappingException("invalid mapping", null,
						(Throwable) errors.get(0));
			add(doc);
			configuration = this;
		} catch (DocumentException e) {
			throw new InvalidMappingException("input stream", null, e);
		}
		try {
			try {
				xmlInputStream.close();
			} catch (IOException ioe) {
				log.warn("Could not close input stream", ioe);
			}
			return configuration;
		} catch (Exception exception) {
			try {
				xmlInputStream.close();
			} catch (IOException ioe) {
				log.warn("Could not close input stream", ioe);
			}
			throw new MappingException(exception);
		}
	}

	public Configuration addResource(String resourceName,
			ClassLoader classLoader) throws MappingException {
		log.info("Reading mappings from resource: " + resourceName);
		InputStream rsrc = classLoader.getResourceAsStream(resourceName);
		if (rsrc == null)
			throw new MappingNotFoundException("resource", resourceName);
		try {
			return addInputStream(rsrc);
		} catch (MappingException me) {
			throw new InvalidMappingException("resource", resourceName, me);
		}
	}

	public Configuration addResource(String resourceName)
			throws MappingException {
		log.info("Reading mappings from resource : " + resourceName);
		ClassLoader contextClassLoader = Thread.currentThread()
				.getContextClassLoader();
		InputStream rsrc = null;
		if (contextClassLoader != null)
			rsrc = contextClassLoader.getResourceAsStream(resourceName);
		if (rsrc == null)
			rsrc = (org.hibernate.cfg.Environment.class).getClassLoader()
					.getResourceAsStream(resourceName);
		if (rsrc == null)
			throw new MappingNotFoundException("resource", resourceName);
		try {
			return addInputStream(rsrc);
		} catch (MappingException me) {
			throw new InvalidMappingException("resource", resourceName, me);
		}
	}

	public Configuration addClass(Class persistentClass)
			throws MappingException {
		String mappingResourceName = persistentClass.getName()
				.replace('.', '/')
				+ ".hbm.xml";
		log.info("Reading mappings from resource: " + mappingResourceName);
		return addResource(mappingResourceName, persistentClass
				.getClassLoader());
	}

	public Configuration addJar(File jar) throws MappingException {
		JarFile jarFile;
		log.info("Searching for mapping documents in jar: " + jar.getName());
		jarFile = null;
		try {
			jarFile = new JarFile(jar);
		} catch (IOException ioe) {
			throw new InvalidMappingException(
					"Could not read mapping documents from jar: "
							+ jar.getName(), "jar", jar.getName(), ioe);
		}
		Enumeration jarEntries = jarFile.entries();
		do {
			if (!jarEntries.hasMoreElements())
				break;
			ZipEntry ze = (ZipEntry) jarEntries.nextElement();
			if (ze.getName().endsWith(".hbm.xml")) {
				log.info("Found mapping document in jar: " + ze.getName());
				try {
					addInputStream(jarFile.getInputStream(ze));
				} catch (Exception e) {
					throw new InvalidMappingException(
							"Could not read mapping documents from jar: "
									+ jar.getName(), "jar", jar.getName(), e);
				}
			}
		} while (true);
		try {
			if (jarFile != null)
				jarFile.close();
		} catch (IOException ioe) {
			log.error("could not close jar", ioe);
		}
		return this;
	}

	public Configuration addDirectory(File dir) throws MappingException {
		File files[] = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {
				addDirectory(files[i]);
				continue;
			}
			if (files[i].getName().endsWith(".hbm.xml"))
				addFile(files[i]);
		}

		return this;
	}

	protected void add(Document doc) throws MappingException {
		HbmBinder.bindRoot(doc, createMappings(), CollectionHelper.EMPTY_MAP);
	}

	public Mappings createMappings() {
		return new Mappings(classes, collections, tables, namedQueries,
				namedSqlQueries, sqlResultSetMappings, imports, secondPasses,
				propertyReferences, namingStrategy, typeDefs,
				filterDefinitions, extendsQueue, auxiliaryDatabaseObjects,
				tableNameBinding, columnNameBindingPerTable);
	}

	private Iterator iterateGenerators(Dialect dialect) throws MappingException {
		TreeMap generators = new TreeMap();
		String defaultCatalog = properties
				.getProperty("hibernate.default_catalog");
		String defaultSchema = properties
				.getProperty("hibernate.default_schema");
		Iterator iter = classes.values().iterator();
		do {
			if (!iter.hasNext())
				break;
			PersistentClass pc = (PersistentClass) iter.next();
			if (!pc.isInherited()) {
				org.hibernate.id.IdentifierGenerator ig = pc.getIdentifier()
						.createIdentifierGenerator(dialect, defaultCatalog,
								defaultSchema, (RootClass) pc);
				if (ig instanceof PersistentIdentifierGenerator)
					generators.put(((PersistentIdentifierGenerator) ig)
							.generatorKey(), ig);
			}
		} while (true);
		iter = collections.values().iterator();
		do {
			if (!iter.hasNext())
				break;
			Collection collection = (Collection) iter.next();
			if (collection.isIdentified()) {
				org.hibernate.id.IdentifierGenerator ig = ((IdentifierCollection) collection)
						.getIdentifier().createIdentifierGenerator(dialect,
								defaultCatalog, defaultSchema, null);
				if (ig instanceof PersistentIdentifierGenerator)
					generators.put(((PersistentIdentifierGenerator) ig)
							.generatorKey(), ig);
			}
		} while (true);
		return generators.values().iterator();
	}

	public String[] generateDropSchemaScript(Dialect dialect)
			throws HibernateException {
		secondPassCompile();
		String defaultCatalog = properties
				.getProperty("hibernate.default_catalog");
		String defaultSchema = properties
				.getProperty("hibernate.default_schema");
		ArrayList script = new ArrayList(50);
		ListIterator itr = auxiliaryDatabaseObjects
				.listIterator(auxiliaryDatabaseObjects.size());
		do {
			if (!itr.hasPrevious())
				break;
			AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr
					.previous();
			if (object.appliesToDialect(dialect))
				script.add(object.sqlDropString(dialect, defaultCatalog,
						defaultSchema));
		} while (true);
		Iterator iter;
		if (dialect.dropConstraints())
			for (iter = getTableMappings(); iter.hasNext();) {
				Table table = (Table) iter.next();
				if (table.isPhysicalTable()) {
					Iterator subIter = table.getForeignKeyIterator();
					while (subIter.hasNext()) {
						ForeignKey fk = (ForeignKey) subIter.next();
						if (fk.isPhysicalConstraint())
							script.add(fk.sqlDropString(dialect,
									defaultCatalog, defaultSchema));
					}
				}
			}

		iter = getTableMappings();
		do {
			if (!iter.hasNext())
				break;
			Table table = (Table) iter.next();
			if (table.isPhysicalTable())
				script.add(table.sqlDropString(dialect, defaultCatalog,
						defaultSchema));
		} while (true);
		for (iter = iterateGenerators(dialect); iter.hasNext();) {
			String lines[] = ((PersistentIdentifierGenerator) iter.next())
					.sqlDropStrings(dialect);
			int i = 0;
			while (i < lines.length) {
				script.add(lines[i]);
				i++;
			}
		}

		return ArrayHelper.toStringArray(script);
	}

	public String[] generateSchemaCreationScript(Dialect dialect)
			throws HibernateException {
		secondPassCompile();
		ArrayList script = new ArrayList(50);
		String defaultCatalog = properties
				.getProperty("hibernate.default_catalog");
		String defaultSchema = properties
				.getProperty("hibernate.default_schema");
		Iterator iter = getTableMappings();
		do {
			if (!iter.hasNext())
				break;
			Table table = (Table) iter.next();
			if (table.isPhysicalTable()) {
				script.add(table.sqlCreateString(dialect, mapping,
						defaultCatalog, defaultSchema));
				Iterator comments = table.sqlCommentStrings(dialect,
						defaultCatalog, defaultSchema);
				while (comments.hasNext())
					script.add(comments.next());
			}
		} while (true);
		for (iter = getTableMappings(); iter.hasNext();) {
			Table table = (Table) iter.next();
			if (table.isPhysicalTable()) {
				if (!dialect.supportsUniqueConstraintInCreateAlterTable()) {
					Iterator subIter = table.getUniqueKeyIterator();
					do {
						if (!subIter.hasNext())
							break;
						UniqueKey uk = (UniqueKey) subIter.next();
						String constraintString = uk.sqlCreateString(dialect,
								mapping, defaultCatalog, defaultSchema);
						if (constraintString != null)
							script.add(constraintString);
					} while (true);
				}
				Index index;
				for (Iterator subIter = table.getIndexIterator(); subIter
						.hasNext(); script.add(index.sqlCreateString(dialect,
						mapping, defaultCatalog, defaultSchema)))
					index = (Index) subIter.next();

				if (dialect.hasAlterTable()) {
					Iterator subIter = table.getForeignKeyIterator();
					while (subIter.hasNext()) {
						ForeignKey fk = (ForeignKey) subIter.next();
						if (fk.isPhysicalConstraint())
							script.add(fk.sqlCreateString(dialect, mapping,
									defaultCatalog, defaultSchema));
					}
				}
			}
		}

		for (iter = iterateGenerators(dialect); iter.hasNext();) {
			String lines[] = ((PersistentIdentifierGenerator) iter.next())
					.sqlCreateStrings(dialect);
			int i = 0;
			while (i < lines.length) {
				script.add(lines[i]);
				i++;
			}
		}

		Iterator itr = auxiliaryDatabaseObjects.iterator();
		do {
			if (!itr.hasNext())
				break;
			AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr
					.next();
			if (object.appliesToDialect(dialect))
				script.add(object.sqlCreateString(dialect, mapping,
						defaultCatalog, defaultSchema));
		} while (true);
		return ArrayHelper.toStringArray(script);
	}

	public String[] generateSchemaUpdateScript(Dialect dialect,
			DatabaseMetadata databaseMetadata) throws HibernateException {
		secondPassCompile();
		String defaultCatalog = properties
				.getProperty("hibernate.default_catalog");
		String defaultSchema = properties
				.getProperty("hibernate.default_schema");
		ArrayList script = new ArrayList(50);
		Iterator iter = getTableMappings();
		do {
			if (!iter.hasNext())
				break;
			Table table = (Table) iter.next();
			if (table.isPhysicalTable()) {
				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
						table.getName(), table.getSchema() != null ? table
								.getSchema() : defaultSchema, table
								.getCatalog() != null ? table.getCatalog()
								: defaultCatalog, table.isQuoted());
				if (tableInfo == null) {
					script.add(table.sqlCreateString(dialect, mapping,
							defaultCatalog, defaultSchema));
				} else {
					for (Iterator subiter = table.sqlAlterStrings(dialect,
							mapping, tableInfo, defaultCatalog, defaultSchema); subiter
							.hasNext(); script.add(subiter.next()))
						;
				}
				Iterator comments = table.sqlCommentStrings(dialect,
						defaultCatalog, defaultSchema);
				while (comments.hasNext())
					script.add(comments.next());
			}
		} while (true);
		for (iter = getTableMappings(); iter.hasNext();) {
			Table table = (Table) iter.next();
			if (table.isPhysicalTable()) {
				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
						table.getName(), table.getSchema(), table.getCatalog(),
						table.isQuoted());
				if (dialect.hasAlterTable()) {
					Iterator subIter = table.getForeignKeyIterator();
					while (subIter.hasNext()) {
						ForeignKey fk = (ForeignKey) subIter.next();
						if (fk.isPhysicalConstraint()) {
							boolean create = tableInfo == null
									|| tableInfo.getForeignKeyMetadata(fk
											.getName()) == null
									&& (!(dialect instanceof MySQLDialect) || tableInfo
											.getIndexMetadata(fk.getName()) == null);
							if (create)
								script.add(fk.sqlCreateString(dialect, mapping,
										defaultCatalog, defaultSchema));
						}
					}
				}
			}
		}

		iter = iterateGenerators(dialect);
		do {
			if (!iter.hasNext())
				break;
			PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter
					.next();
			Object key = generator.generatorKey();
			if (!databaseMetadata.isSequence(key)
					&& !databaseMetadata.isTable(key)) {
				String lines[] = generator.sqlCreateStrings(dialect);
				int i = 0;
				while (i < lines.length) {
					script.add(lines[i]);
					i++;
				}
			}
		} while (true);
		return ArrayHelper.toStringArray(script);
	}

	public void validateSchema(Dialect dialect,
			DatabaseMetadata databaseMetadata) throws HibernateException {
		secondPassCompile();
		String defaultCatalog = properties
				.getProperty("hibernate.default_catalog");
		String defaultSchema = properties
				.getProperty("hibernate.default_schema");
		Iterator iter = getTableMappings();
		do {
			if (!iter.hasNext())
				break;
			Table table = (Table) iter.next();
			if (table.isPhysicalTable()) {
				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
						table.getName(), table.getSchema() != null ? table
								.getSchema() : defaultSchema, table
								.getCatalog() != null ? table.getCatalog()
								: defaultCatalog, table.isQuoted());
				if (tableInfo == null)
					throw new HibernateException("Missing table: "
							+ table.getName());
				table.validateColumns(dialect, mapping, tableInfo);
			}
		} while (true);
		for (iter = iterateGenerators(dialect); iter.hasNext();) {
			PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter
					.next();
			Object key = generator.generatorKey();
			if (!databaseMetadata.isSequence(key)
					&& !databaseMetadata.isTable(key))
				throw new HibernateException("Missing sequence or table: "
						+ key);
		}

	}

	private void validate() throws MappingException {
		for (Iterator iter = classes.values().iterator(); iter.hasNext(); ((PersistentClass) iter
				.next()).validate(mapping))
			;
		for (Iterator iter = collections.values().iterator(); iter.hasNext(); ((Collection) iter
				.next()).validate(mapping))
			;
	}

	public void buildMappings() {
		secondPassCompile();
	}

	protected void secondPassCompile() throws MappingException {
		log.debug("processing extends queue");
		processExtendsQueue();
		log.debug("processing collection mappings");
		Iterator iter = secondPasses.iterator();
		do {
			if (!iter.hasNext())
				break;
			SecondPass sp = (SecondPass) iter.next();
			if (!(sp instanceof QuerySecondPass)) {
				sp.doSecondPass(classes);
				iter.remove();
			}
		} while (true);
		log.debug("processing native query and ResultSetMapping mappings");
		for (iter = secondPasses.iterator(); iter.hasNext(); iter.remove()) {
			SecondPass sp = (SecondPass) iter.next();
			sp.doSecondPass(classes);
		}

		log.debug("processing association property references");
		iter = propertyReferences.iterator();
		do {
			if (!iter.hasNext())
				break;
			Mappings.PropertyReference upr = (Mappings.PropertyReference) iter
					.next();
			PersistentClass clazz = getClassMapping(upr.referencedClass);
			if (clazz == null)
				throw new MappingException("property-ref to unmapped class: "
						+ upr.referencedClass);
			Property prop = clazz.getReferencedProperty(upr.propertyName);
			if (upr.unique)
				((SimpleValue) prop.getValue()).setAlternateUniqueKey(true);
		} while (true);
		log.debug("processing foreign key constraints");
		iter = getTableMappings();
		Set done = new HashSet();
		for (; iter.hasNext(); secondPassCompileForeignKeys(
				(Table) iter.next(), done))
			;
	}

	private void processExtendsQueue() {
		for (Document document = findPossibleExtends(); document != null; document = findPossibleExtends())
			add(document);

		if (extendsQueue.size() > 0) {
			Iterator iterator = extendsQueue.keySet().iterator();
			StringBuffer buf = new StringBuffer(
					"Following superclasses referenced in extends not found: ");
			do {
				if (!iterator.hasNext())
					break;
				ExtendsQueueEntry entry = (ExtendsQueueEntry) iterator.next();
				buf.append(entry.getExplicitName());
				if (entry.getMappingPackage() != null)
					buf.append("[").append(entry.getMappingPackage()).append(
							"]");
				if (iterator.hasNext())
					buf.append(",");
			} while (true);
			throw new MappingException(buf.toString());
		} else {
			return;
		}
	}

	protected Document findPossibleExtends() {
		for (Iterator iter = extendsQueue.keySet().iterator(); iter.hasNext();) {
			ExtendsQueueEntry entry = (ExtendsQueueEntry) iter.next();
			if (getClassMapping(entry.getExplicitName()) != null) {
				iter.remove();
				return entry.getDocument();
			}
			if (getClassMapping(HbmBinder.getClassName(entry.getExplicitName(),
					entry.getMappingPackage())) != null) {
				iter.remove();
				return entry.getDocument();
			}
		}

		return null;
	}

	protected void secondPassCompileForeignKeys(Table table, Set done)
			throws MappingException {
		table.createForeignKeys();
		Iterator iter = table.getForeignKeyIterator();
		do {
			if (!iter.hasNext())
				break;
			ForeignKey fk = (ForeignKey) iter.next();
			if (!done.contains(fk)) {
				done.add(fk);
				String referencedEntityName = fk.getReferencedEntityName();
				if (referencedEntityName == null)
					throw new MappingException("An association from the table "
							+ fk.getTable().getName()
							+ " does not specify the referenced entity");
				if (log.isDebugEnabled())
					log.debug("resolving reference to class: "
							+ referencedEntityName);
				PersistentClass referencedClass = (PersistentClass) classes
						.get(referencedEntityName);
				if (referencedClass == null)
					throw new MappingException("An association from the table "
							+ fk.getTable().getName()
							+ " refers to an unmapped class: "
							+ referencedEntityName);
				if (referencedClass.isJoinedSubclass())
					secondPassCompileForeignKeys(referencedClass
							.getSuperclass().getTable(), done);
				fk.setReferencedTable(referencedClass.getTable());
				fk.alignColumns();
			}
		} while (true);
	}

	public Map getNamedQueries() {
		return namedQueries;
	}

	public SessionFactory buildSessionFactory() throws HibernateException {
		log.debug("Preparing to build session factory with filters : "
				+ filterDefinitions);
		secondPassCompile();
		validate();
		Environment.verifyProperties(properties);
		Properties copy = new Properties();
		copy.putAll(properties);
		PropertiesHelper.resolvePlaceHolders(copy);
		Settings settings = buildSettings(copy);
		return new SessionFactoryImpl(this, mapping, settings,
				getInitializedEventListeners(), sessionFactoryObserver);
	}

	private EventListeners getInitializedEventListeners() {
		EventListeners result = (EventListeners) eventListeners.shallowCopy();
		result.initializeListeners(this);
		return result;
	}

	public Interceptor getInterceptor() {
		return interceptor;
	}

	public Properties getProperties() {
		return properties;
	}

	public Configuration setInterceptor(Interceptor interceptor) {
		this.interceptor = interceptor;
		return this;
	}

	public Configuration setProperties(Properties properties) {
		this.properties = properties;
		return this;
	}

	public Configuration addProperties(Properties extraProperties) {
		properties.putAll(extraProperties);
		return this;
	}

	public Configuration mergeProperties(Properties properties) {
		Iterator itr = properties.entrySet().iterator();
		do {
			if (!itr.hasNext())
				break;
			java.util.Map.Entry entry = (java.util.Map.Entry) itr.next();
			if (!this.properties.containsKey(entry.getKey()))
				this.properties.setProperty((String) entry.getKey(),
						(String) entry.getValue());
		} while (true);
		return this;
	}

	public Configuration setProperty(String propertyName, String value) {
		properties.setProperty(propertyName, value);
		return this;
	}

	public String getProperty(String propertyName) {
		return properties.getProperty(propertyName);
	}

	private void addProperties(Element parent) {
		Iterator iter = parent.elementIterator("property");
		do {
			if (!iter.hasNext())
				break;
			Element node = (Element) iter.next();
			String name = node.attributeValue("name");
			String value = node.getText().trim();
			log.debug(name + "=" + value);
			properties.setProperty(name, value);
			if (!name.startsWith("hibernate"))
				properties.setProperty("hibernate." + name, value);
		} while (true);
		Environment.verifyProperties(properties);
	}

	protected InputStream getConfigurationInputStream(String resource)
			throws HibernateException {
		log.info("Configuration resource: " + resource);
		return ConfigHelper.getResourceAsStream(resource);
	}

	public Configuration configure() throws HibernateException {
		configure("/hibernate.cfg.xml");
		return this;
	}

	public Configuration configure(String resource) throws HibernateException {
		log.info("configuring from resource: " + resource);
		InputStream stream = getConfigurationInputStream(resource);
		return doConfigure(stream, resource);
	}

	public Configuration configure(URL url) throws HibernateException {
		log.info("configuring from url: " + url.toString());
		try {
			return doConfigure(url.openStream(), url.toString());
		} catch (IOException ioe) {
			throw new HibernateException(
					"could not configure from URL: " + url, ioe);
		}
	}

	public Configuration configure(File configFile) throws HibernateException {
		log.info("configuring from file: " + configFile.getName());
		try {
			return doConfigure(new FileInputStream(configFile), configFile
					.toString());
		} catch (FileNotFoundException fnfe) {
			throw new HibernateException("could not find file: " + configFile,
					fnfe);
		}
	}

	protected Configuration doConfigure(InputStream stream, String resourceName)
			throws HibernateException {
		Document doc;
		try {
			List errors = new ArrayList();
			doc = xmlHelper.createSAXReader(resourceName, errors,
					entityResolver).read(new InputSource(stream));
			if (errors.size() != 0)
				throw new MappingException("invalid configuration",
						(Throwable) errors.get(0));
		} catch (DocumentException e) {
			throw new HibernateException("Could not parse configuration: "
					+ resourceName, e);
		}
		try {
			stream.close();
		} catch (IOException ioe) {
			log.warn("could not close input stream for: " + resourceName, ioe);
		}
		return doConfigure(doc);
	}

	public Configuration configure(org.w3c.dom.Document document)
			throws HibernateException {
		log.info("configuring from XML document");
		return doConfigure(xmlHelper.createDOMReader().read(document));
	}

	protected Configuration doConfigure(Document doc) throws HibernateException {
		Element sfNode = doc.getRootElement().element("session-factory");
		String name = sfNode.attributeValue("name");
		if (name != null)
			properties.setProperty("hibernate.session_factory_name", name);
		addProperties(sfNode);
		parseSessionFactory(sfNode, name);
		Element secNode = doc.getRootElement().element("security");
		if (secNode != null)
			parseSecurity(secNode);
		log.info("Configured SessionFactory: " + name);
		log.debug("properties: " + properties);
		return this;
	}

	private void parseSessionFactory(Element sfNode, String name) {
		Iterator elements = sfNode.elementIterator();
		do {
			if (!elements.hasNext())
				break;
			Element subelement = (Element) elements.next();
			String subelementName = subelement.getName();
			if ("mapping".equals(subelementName))
				parseMappingElement(subelement, name);
			else if ("class-cache".equals(subelementName)) {
				String className = subelement.attributeValue("class");
				Attribute regionNode = subelement.attribute("region");
				String region = regionNode != null ? regionNode.getValue()
						: className;
				boolean includeLazy = !"non-lazy".equals(subelement
						.attributeValue("include"));
				setCacheConcurrencyStrategy(className, subelement
						.attributeValue("usage"), region, includeLazy);
			} else if ("collection-cache".equals(subelementName)) {
				String role = subelement.attributeValue("collection");
				Attribute regionNode = subelement.attribute("region");
				String region = regionNode != null ? regionNode.getValue()
						: role;
				setCollectionCacheConcurrencyStrategy(role, subelement
						.attributeValue("usage"), region);
			} else if ("listener".equals(subelementName))
				parseListener(subelement);
			else if ("event".equals(subelementName))
				parseEvent(subelement);
		} while (true);
	}

	protected void parseMappingElement(Element subelement, String name) {
		Attribute rsrc = subelement.attribute("resource");
		Attribute file = subelement.attribute("file");
		Attribute jar = subelement.attribute("jar");
		Attribute pkg = subelement.attribute("package");
		Attribute clazz = subelement.attribute("class");
		if (rsrc != null) {
			log.debug(name + "<-" + rsrc);
			addResource(rsrc.getValue());
		} else if (jar != null) {
			log.debug(name + "<-" + jar);
			addJar(new File(jar.getValue()));
		} else {
			if (pkg != null)
				throw new MappingException(
						"An AnnotationConfiguration instance is required to use <mapping package=\""
								+ pkg.getValue() + "\"/>");
			if (clazz != null)
				throw new MappingException(
						"An AnnotationConfiguration instance is required to use <mapping class=\""
								+ clazz.getValue() + "\"/>");
			if (file == null)
				throw new MappingException(
						"<mapping> element in configuration specifies no attributes");
			log.debug(name + "<-" + file);
			addFile(file.getValue());
		}
	}

	private void parseSecurity(Element secNode) {
		String contextId = secNode.attributeValue("context");
		setProperty("hibernate.jacc_context_id", contextId);
		log.info("JACC contextID: " + contextId);
		JACCConfiguration jcfg = new JACCConfiguration(contextId);
		Iterator grantElements = secNode.elementIterator();
		do {
			if (!grantElements.hasNext())
				break;
			Element grantElement = (Element) grantElements.next();
			String elementName = grantElement.getName();
			if ("grant".equals(elementName))
				jcfg.addPermission(grantElement.attributeValue("role"),
						grantElement.attributeValue("entity-name"),
						grantElement.attributeValue("actions"));
		} while (true);
	}

	private void parseEvent(Element element) {
		String type = element.attributeValue("type");
		List listeners = element.elements();
		String listenerClasses[] = new String[listeners.size()];
		for (int i = 0; i < listeners.size(); i++)
			listenerClasses[i] = ((Element) listeners.get(i))
					.attributeValue("class");

		log.debug("Event listeners: " + type + "="
				+ StringHelper.toString(listenerClasses));
		setListeners(type, listenerClasses);
	}

	private void parseListener(Element element) {
		String type = element.attributeValue("type");
		if (type == null) {
			throw new MappingException("No type specified for listener");
		} else {
			String impl = element.attributeValue("class");
			log.debug("Event listener: " + type + "=" + impl);
			setListeners(type, new String[] { impl });
			return;
		}
	}

	public void setListener(String type, String listener) {
		String listeners[] = null;
		if (listener != null) {
			listeners = (String[]) (String[]) Array.newInstance(
					java.lang.String.class, 1);
			listeners[0] = listener;
		}
		setListeners(type, listeners);
	}

	public void setListeners(String type, String listenerClasses[]) {
		Object listeners[] = null;
		if (listenerClasses != null) {
			listeners = (Object[]) (Object[]) Array.newInstance(eventListeners
					.getListenerClassFor(type), listenerClasses.length);
			for (int i = 0; i < listeners.length; i++)
				try {
					listeners[i] = ReflectHelper.classForName(
							listenerClasses[i]).newInstance();
				} catch (Exception e) {
					throw new MappingException(
							"Unable to instantiate specified event (" + type
									+ ") listener class: " + listenerClasses[i],
							e);
				}

		}
		setListeners(type, listeners);
	}

	public void setListener(String type, Object listener) {
		Object listeners[] = null;
		if (listener != null) {
			listeners = (Object[]) (Object[]) Array.newInstance(eventListeners
					.getListenerClassFor(type), 1);
			listeners[0] = listener;
		}
		setListeners(type, listeners);
	}

	public void setListeners(String type, Object listeners[]) {
		if ("auto-flush".equals(type)) {
			if (listeners == null)
				eventListeners
						.setAutoFlushEventListeners(new AutoFlushEventListener[0]);
			else
				eventListeners
						.setAutoFlushEventListeners((AutoFlushEventListener[]) (AutoFlushEventListener[]) listeners);
		} else if ("merge".equals(type)) {
			if (listeners == null)
				eventListeners
						.setMergeEventListeners(new MergeEventListener[0]);
			else
				eventListeners
						.setMergeEventListeners((MergeEventListener[]) (MergeEventListener[]) listeners);
		} else if ("create".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPersistEventListeners(new PersistEventListener[0]);
			else
				eventListeners
						.setPersistEventListeners((PersistEventListener[]) (PersistEventListener[]) listeners);
		} else if ("create-onflush".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPersistOnFlushEventListeners(new PersistEventListener[0]);
			else
				eventListeners
						.setPersistOnFlushEventListeners((PersistEventListener[]) (PersistEventListener[]) listeners);
		} else if ("delete".equals(type)) {
			if (listeners == null)
				eventListeners
						.setDeleteEventListeners(new DeleteEventListener[0]);
			else
				eventListeners
						.setDeleteEventListeners((DeleteEventListener[]) (DeleteEventListener[]) listeners);
		} else if ("dirty-check".equals(type)) {
			if (listeners == null)
				eventListeners
						.setDirtyCheckEventListeners(new DirtyCheckEventListener[0]);
			else
				eventListeners
						.setDirtyCheckEventListeners((DirtyCheckEventListener[]) (DirtyCheckEventListener[]) listeners);
		} else if ("evict".equals(type)) {
			if (listeners == null)
				eventListeners
						.setEvictEventListeners(new EvictEventListener[0]);
			else
				eventListeners
						.setEvictEventListeners((EvictEventListener[]) (EvictEventListener[]) listeners);
		} else if ("flush".equals(type)) {
			if (listeners == null)
				eventListeners
						.setFlushEventListeners(new FlushEventListener[0]);
			else
				eventListeners
						.setFlushEventListeners((FlushEventListener[]) (FlushEventListener[]) listeners);
		} else if ("flush-entity".equals(type)) {
			if (listeners == null)
				eventListeners
						.setFlushEntityEventListeners(new FlushEntityEventListener[0]);
			else
				eventListeners
						.setFlushEntityEventListeners((FlushEntityEventListener[]) (FlushEntityEventListener[]) listeners);
		} else if ("load".equals(type)) {
			if (listeners == null)
				eventListeners.setLoadEventListeners(new LoadEventListener[0]);
			else
				eventListeners
						.setLoadEventListeners((LoadEventListener[]) (LoadEventListener[]) listeners);
		} else if ("load-collection".equals(type)) {
			if (listeners == null)
				eventListeners
						.setInitializeCollectionEventListeners(new InitializeCollectionEventListener[0]);
			else
				eventListeners
						.setInitializeCollectionEventListeners((InitializeCollectionEventListener[]) (InitializeCollectionEventListener[]) listeners);
		} else if ("lock".equals(type)) {
			if (listeners == null)
				eventListeners.setLockEventListeners(new LockEventListener[0]);
			else
				eventListeners
						.setLockEventListeners((LockEventListener[]) (LockEventListener[]) listeners);
		} else if ("refresh".equals(type)) {
			if (listeners == null)
				eventListeners
						.setRefreshEventListeners(new RefreshEventListener[0]);
			else
				eventListeners
						.setRefreshEventListeners((RefreshEventListener[]) (RefreshEventListener[]) listeners);
		} else if ("replicate".equals(type)) {
			if (listeners == null)
				eventListeners
						.setReplicateEventListeners(new ReplicateEventListener[0]);
			else
				eventListeners
						.setReplicateEventListeners((ReplicateEventListener[]) (ReplicateEventListener[]) listeners);
		} else if ("save-update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setSaveOrUpdateEventListeners(new SaveOrUpdateEventListener[0]);
			else
				eventListeners
						.setSaveOrUpdateEventListeners((SaveOrUpdateEventListener[]) (SaveOrUpdateEventListener[]) listeners);
		} else if ("save".equals(type)) {
			if (listeners == null)
				eventListeners
						.setSaveEventListeners(new SaveOrUpdateEventListener[0]);
			else
				eventListeners
						.setSaveEventListeners((SaveOrUpdateEventListener[]) (SaveOrUpdateEventListener[]) listeners);
		} else if ("update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setUpdateEventListeners(new SaveOrUpdateEventListener[0]);
			else
				eventListeners
						.setUpdateEventListeners((SaveOrUpdateEventListener[]) (SaveOrUpdateEventListener[]) listeners);
		} else if ("pre-load".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreLoadEventListeners(new PreLoadEventListener[0]);
			else
				eventListeners
						.setPreLoadEventListeners((PreLoadEventListener[]) (PreLoadEventListener[]) listeners);
		} else if ("pre-update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreUpdateEventListeners(new PreUpdateEventListener[0]);
			else
				eventListeners
						.setPreUpdateEventListeners((PreUpdateEventListener[]) (PreUpdateEventListener[]) listeners);
		} else if ("pre-delete".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreDeleteEventListeners(new PreDeleteEventListener[0]);
			else
				eventListeners
						.setPreDeleteEventListeners((PreDeleteEventListener[]) (PreDeleteEventListener[]) listeners);
		} else if ("pre-insert".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreInsertEventListeners(new PreInsertEventListener[0]);
			else
				eventListeners
						.setPreInsertEventListeners((PreInsertEventListener[]) (PreInsertEventListener[]) listeners);
		} else if ("pre-collection-recreate".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreCollectionRecreateEventListeners(new PreCollectionRecreateEventListener[0]);
			else
				eventListeners
						.setPreCollectionRecreateEventListeners((PreCollectionRecreateEventListener[]) (PreCollectionRecreateEventListener[]) listeners);
		} else if ("pre-collection-remove".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreCollectionRemoveEventListeners(new PreCollectionRemoveEventListener[0]);
			else
				eventListeners
						.setPreCollectionRemoveEventListeners((PreCollectionRemoveEventListener[]) (PreCollectionRemoveEventListener[]) listeners);
		} else if ("pre-collection-update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPreCollectionUpdateEventListeners(new PreCollectionUpdateEventListener[0]);
			else
				eventListeners
						.setPreCollectionUpdateEventListeners((PreCollectionUpdateEventListener[]) (PreCollectionUpdateEventListener[]) listeners);
		} else if ("post-load".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostLoadEventListeners(new PostLoadEventListener[0]);
			else
				eventListeners
						.setPostLoadEventListeners((PostLoadEventListener[]) (PostLoadEventListener[]) listeners);
		} else if ("post-update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostUpdateEventListeners(new PostUpdateEventListener[0]);
			else
				eventListeners
						.setPostUpdateEventListeners((PostUpdateEventListener[]) (PostUpdateEventListener[]) listeners);
		} else if ("post-delete".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostDeleteEventListeners(new PostDeleteEventListener[0]);
			else
				eventListeners
						.setPostDeleteEventListeners((PostDeleteEventListener[]) (PostDeleteEventListener[]) listeners);
		} else if ("post-insert".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostInsertEventListeners(new PostInsertEventListener[0]);
			else
				eventListeners
						.setPostInsertEventListeners((PostInsertEventListener[]) (PostInsertEventListener[]) listeners);
		} else if ("post-commit-update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostCommitUpdateEventListeners(new PostUpdateEventListener[0]);
			else
				eventListeners
						.setPostCommitUpdateEventListeners((PostUpdateEventListener[]) (PostUpdateEventListener[]) listeners);
		} else if ("post-commit-delete".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostCommitDeleteEventListeners(new PostDeleteEventListener[0]);
			else
				eventListeners
						.setPostCommitDeleteEventListeners((PostDeleteEventListener[]) (PostDeleteEventListener[]) listeners);
		} else if ("post-commit-insert".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostCommitInsertEventListeners(new PostInsertEventListener[0]);
			else
				eventListeners
						.setPostCommitInsertEventListeners((PostInsertEventListener[]) (PostInsertEventListener[]) listeners);
		} else if ("post-collection-recreate".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostCollectionRecreateEventListeners(new PostCollectionRecreateEventListener[0]);
			else
				eventListeners
						.setPostCollectionRecreateEventListeners((PostCollectionRecreateEventListener[]) (PostCollectionRecreateEventListener[]) listeners);
		} else if ("post-collection-remove".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostCollectionRemoveEventListeners(new PostCollectionRemoveEventListener[0]);
			else
				eventListeners
						.setPostCollectionRemoveEventListeners((PostCollectionRemoveEventListener[]) (PostCollectionRemoveEventListener[]) listeners);
		} else if ("post-collection-update".equals(type)) {
			if (listeners == null)
				eventListeners
						.setPostCollectionUpdateEventListeners(new PostCollectionUpdateEventListener[0]);
			else
				eventListeners
						.setPostCollectionUpdateEventListeners((PostCollectionUpdateEventListener[]) (PostCollectionUpdateEventListener[]) listeners);
		} else {
			throw new MappingException("Unrecognized listener type [" + type
					+ "]");
		}
	}

	public EventListeners getEventListeners() {
		return eventListeners;
	}

	RootClass getRootClassMapping(String clazz) throws MappingException {
		try {
			return (RootClass) getClassMapping(clazz);
		} catch (ClassCastException cce) {
			throw new MappingException(
					"You may only specify a cache for root <class> mappings");
		}
	}

	public Configuration setCacheConcurrencyStrategy(String clazz,
			String concurrencyStrategy) throws MappingException {
		setCacheConcurrencyStrategy(clazz, concurrencyStrategy, clazz);
		return this;
	}

	public void setCacheConcurrencyStrategy(String clazz,
			String concurrencyStrategy, String region) throws MappingException {
		setCacheConcurrencyStrategy(clazz, concurrencyStrategy, region, true);
	}

	void setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy,
			String region, boolean includeLazy) throws MappingException {
		RootClass rootClass = getRootClassMapping(clazz);
		if (rootClass == null) {
			throw new MappingException("Cannot cache an unknown entity: "
					+ clazz);
		} else {
			rootClass.setCacheConcurrencyStrategy(concurrencyStrategy);
			rootClass.setCacheRegionName(region);
			rootClass.setLazyPropertiesCacheable(includeLazy);
			return;
		}
	}

	public Configuration setCollectionCacheConcurrencyStrategy(
			String collectionRole, String concurrencyStrategy)
			throws MappingException {
		setCollectionCacheConcurrencyStrategy(collectionRole,
				concurrencyStrategy, collectionRole);
		return this;
	}

	public void setCollectionCacheConcurrencyStrategy(String collectionRole,
			String concurrencyStrategy, String region) throws MappingException {
		Collection collection = getCollectionMapping(collectionRole);
		if (collection == null) {
			throw new MappingException("Cannot cache an unknown collection: "
					+ collectionRole);
		} else {
			collection.setCacheConcurrencyStrategy(concurrencyStrategy);
			collection.setCacheRegionName(region);
			return;
		}
	}

	public Map getImports() {
		return imports;
	}

	public Settings buildSettings() throws HibernateException {
		Properties clone = (Properties) properties.clone();
		PropertiesHelper.resolvePlaceHolders(clone);
		return settingsFactory.buildSettings(clone);
	}

	public Settings buildSettings(Properties props) throws HibernateException {
		return settingsFactory.buildSettings(props);
	}

	public Map getNamedSQLQueries() {
		return namedSqlQueries;
	}

	public Map getSqlResultSetMappings() {
		return sqlResultSetMappings;
	}

	public NamingStrategy getNamingStrategy() {
		return namingStrategy;
	}

	public Configuration setNamingStrategy(NamingStrategy namingStrategy) {
		this.namingStrategy = namingStrategy;
		return this;
	}

	public Mapping buildMapping() {
		return new Mapping() {

			public Type getIdentifierType(String persistentClass)
					throws MappingException {
				PersistentClass pc = (PersistentClass) classes
						.get(persistentClass);
				if (pc == null)
					throw new MappingException("persistent class not known: "
							+ persistentClass);
				else
					return pc.getIdentifier().getType();
			}

			public String getIdentifierPropertyName(String persistentClass)
					throws MappingException {
				PersistentClass pc = (PersistentClass) classes
						.get(persistentClass);
				if (pc == null)
					throw new MappingException("persistent class not known: "
							+ persistentClass);
				if (!pc.hasIdentifierProperty())
					return null;
				else
					return pc.getIdentifierProperty().getName();
			}

			public Type getReferencedPropertyType(String persistentClass,
					String propertyName) throws MappingException {
				PersistentClass pc = (PersistentClass) classes
						.get(persistentClass);
				if (pc == null)
					throw new MappingException("persistent class not known: "
							+ persistentClass);
				Property prop = pc.getReferencedProperty(propertyName);
				if (prop == null)
					throw new MappingException("property not known: "
							+ persistentClass + '.' + propertyName);
				else
					return prop.getType();
			}
		};
	}

	private void readObject(ObjectInputStream ois) throws IOException,
			ClassNotFoundException {
		ois.defaultReadObject();
		mapping = buildMapping();
		xmlHelper = new XMLHelper();
	}

	public Map getFilterDefinitions() {
		return filterDefinitions;
	}

	public void addFilterDefinition(FilterDefinition definition) {
		filterDefinitions.put(definition.getFilterName(), definition);
	}

	public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) {
		auxiliaryDatabaseObjects.add(object);
	}

	public Map getSqlFunctions() {
		return sqlFunctions;
	}

	public void addSqlFunction(String functionName, SQLFunction function) {
		sqlFunctions.put(functionName, function);
	}

	public SessionFactoryObserver getSessionFactoryObserver() {
		return sessionFactoryObserver;
	}

	public void setSessionFactoryObserver(
			SessionFactoryObserver sessionFactoryObserver) {
		this.sessionFactoryObserver = sessionFactoryObserver;
	}

}
